package cn.schoolwow.quickdao.module.database.dql.query.kit;

import cn.schoolwow.quickdao.domain.entity.Entity;
import cn.schoolwow.quickdao.domain.entity.Property;
import cn.schoolwow.quickdao.module.database.dql.condition.domain.SFunction;
import cn.schoolwow.quickdao.module.database.dql.query.service.FetchListFlow;
import cn.schoolwow.quickdao.module.database.dql.query.service.FetchNullFlow;
import cn.schoolwow.quickdao.module.database.parent.domain.ResultSetConsumer;
import cn.schoolwow.quickdao.module.database.parent.flow.executor.ExecuteQueryConnectionFlow;
import cn.schoolwow.quickdao.module.database.parent.kit.DatabaseDAOImpl;
import cn.schoolwow.quickdao.util.LambdaUtils;
import cn.schoolwow.quickflow.QuickFlow;
import cn.schoolwow.quickflow.QuickFlowExecutor;
import cn.schoolwow.quickflow.domain.FlowContext;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.util.Arrays;
import java.util.List;

public class DatabaseQueryImpl extends DatabaseDAOImpl implements DatabaseQuery {

    public DatabaseQueryImpl(QuickFlow quickFlow) {
        super(quickFlow);
    }

    @Override
    public <T> T fetch(Class<T> clazz, long id) {
        Entity entity = quickDAOConfig.getEntityByClassName(clazz.getName());
        return fetch(clazz, entity.id.column, id);
    }

    @Override
    public <T> T fetch(Class<T> clazz, String field, Object value) {
        List<T> list = fetchList(clazz, field, value);
        if (null == list || list.isEmpty()) {
            return null;
        }
        return list.get(0);
    }

    @Override
    public <T> List<T> fetchList(Class<T> clazz, String fieldName, Object value) {
        Entity entity = quickDAOConfig.getEntityByClassName(clazz.getName());
        if (null == entity) {
            throw new IllegalArgumentException("数据库表不存在!实体类名:" + clazz.getName());
        }
        Property property = entity.getPropertyByFieldNameOrColumnName(fieldName);
        if(null==property){
            throw new IllegalArgumentException("数据库表字段不存在!实体类名:" + clazz.getName()+",字段:"+fieldName);
        }
        JSONArray array = fetchList(entity, property.column, value);
        return array.toJavaList(clazz);
    }

    @Override
    public <T> T fetch(Class<T> clazz, SFunction<T, ?> field, Object value) {
        String convertField = LambdaUtils.resolveLambdaProperty(field);
        return fetch(clazz, convertField, value);
    }

    @Override
    public <T> List<T> fetchList(Class<T> clazz, SFunction<T, ?> field, Object value) {
        String convertField = LambdaUtils.resolveLambdaProperty(field);
        return fetchList(clazz, convertField, value);
    }

    @Override
    public JSONObject fetch(String tableName, String columnName, Object value) {
        JSONArray array = fetchList(tableName, columnName, value);
        if (null == array || array.isEmpty()) {
            return null;
        }
        return array.getJSONObject(0);
    }

    @Override
    public JSONArray fetchList(String tableName, String columnName, Object value) {
        Entity entity = quickDAOConfig.getDatabaseEntityByTableName(tableName);
        if (null == entity) {
            throw new IllegalArgumentException("数据库表不存在!表名:" + tableName);
        }
        JSONArray array = fetchList(entity, columnName, value);
        return array;
    }

    @Override
    public JSONArray rawSelect(String selectSQL, Object... parameters) {
        JSONArray array = new JSONArray();
        quickFlow.startFlow(new ExecuteQueryConnectionFlow())
                .putTemporaryData("name", "用户自定义查询")
                .putTemporaryData("sql", selectSQL)
                .putTemporaryData("parameters", Arrays.asList(parameters))
                .putReturnData("resultSetConsumer",new ResultSetConsumer() {
                    @Override
                    public void consumeResultSet(ResultSet resultSet) throws Exception {
                        ResultSetMetaData metaData = resultSet.getMetaData();
                        String[] columnLables = new String[metaData.getColumnCount()];
                        for (int i = 1; i <= columnLables.length; i++) {
                            columnLables[i - 1] = metaData.getColumnLabel(i);
                        }
                        while (resultSet.next()) {
                            JSONObject o = new JSONObject();
                            for (int i = 1; i <= columnLables.length; i++) {
                                o.put(columnLables[i - 1], resultSet.getObject(i));
                            }
                            array.add(o);
                        }
                    }
                })
                .execute();
        return array;
    }

    private JSONArray fetchList(Entity entity, String column, Object value) {
        QuickFlowExecutor quickFlowExecutor = null;
        if(null==value){
            quickFlowExecutor = quickFlow.startFlow(new FetchNullFlow());
        }else{
            quickFlowExecutor = quickFlow.startFlow(new FetchListFlow());
        }

        FlowContext flowContext = quickFlowExecutor.putTemporaryData("entity", entity)
                .putTemporaryData("column", column)
                .putTemporaryData("value", value)
                .execute();
        JSONArray resultSetArray = (JSONArray) flowContext.getData("resultSetArray");
        return resultSetArray;
    }

}
